/*
 * File: concurrent_execution.c
 *
 * Code generated for Simulink model 'concurrent_execution'.
 *
 * Model version                  : 3.1
 * Simulink Coder version         : 9.5 (R2021a) 14-Nov-2020
 * C/C++ source code generated on : Tue Dec 21 10:52:34 2021
 *
 * Target selection: ert.tlc
 * Embedded hardware selection: Intel->x86-64 (Windows64)
 * Code generation objectives: Unspecified
 * Validation result: Not run
 */

#include "concurrent_execution.h"

/* Tasks */
RT_MODEL task_M_[3];
RT_MODEL *task_M[3];

/* Exported block signals */
real_T In1_1s;                         /* '<Root>/In1_1s' */
real_T In2_2s;                         /* '<Root>/In2_2s' */
real_T Out2_1s;                        /* '<Root>/SS2' */
real_T Out1_1s;                        /* '<Root>/Sum' */

/* Block signals and states (default storage) */
DW rtDW;

/* Real-time model */
static RT_MODEL rtM_;
RT_MODEL *const rtM = &rtM_;

/*   This function updates active task counters and model execution time. */
void AdvanceTaskCounters(void)
{
  /* Compute which subrates run during the next base time step.  Subrates
   * are an integer multiple of the base rate counter.  Therefore, the subtask
   * counter is reset when it reaches its limit (zero means run).
   */
  (rtM->Timing.TaskCounters.TID[1])++;
  if ((rtM->Timing.TaskCounters.TID[1]) > 1) {/* Sample time: [2.0s, 0.0s] */
    rtM->Timing.TaskCounters.TID[1] = 0;
  }

  /* Update absolute time for base rate */
  /* The "clockTick0" counts the number of times the code of this task has
   * been executed. The resolution of this integer timer is 1.0, which is the step size
   * of the task. Size of "clockTick0" ensures timer will not overflow during the
   * application lifespan selected.
   */
}

/* OutputUpdate for Task: PeriodicTrigger1_OneSecond */
void PeriodicTrigger1_OneSecond_step(void) /* Sample time: [1.0s, 0.0s] */
{
  /* local block i/o variables */
  real_T rtb_SS1;

  /* RateTransition generated from: '<Root>/Integrator' */
  rtw_win_mutex_wait(rtDW.TmpRTBAtIntegratorOutport1_d0_SEMAPHORE);
  rtDW.TmpRTBAtIntegratorOutport1_RDBuf =
    rtDW.TmpRTBAtIntegratorOutport1_LstBufWR;
  rtw_win_mutex_release(rtDW.TmpRTBAtIntegratorOutport1_d0_SEMAPHORE);

  /* RateTransition generated from: '<Root>/Integrator' */
  rtDW.TmpRTBAtIntegratorOutport1 =
    rtDW.TmpRTBAtIntegratorOutport1_Buf[rtDW.TmpRTBAtIntegratorOutport1_RDBuf];

  /* ModelReference: '<Root>/SS1' incorporates:
   *  Inport: '<Root>/In1_1s'
   */
  ss1(&In1_1s, &rtDW.TmpRTBAtIntegratorOutport1, &rtb_SS1);

  /* TaskTransBlk generated from: '<Root>/SS1' */
  rtDW.TmpTaskTransAtSS1Outport1_buf_1[rtDW.fw_buf_1] = rtb_SS1;
  rtw_win_mutex_wait(rtDW.mw_buf_1);
  rtDW.fw_buf_1 = 1 - rtDW.fw_buf_1;
  rtw_win_mutex_release(rtDW.mw_buf_1);

  /* ModelReference: '<Root>/SS2' incorporates:
   *  Inport: '<Root>/In1_1s'
   */
  ss2(&rtDW.TmpRTBAtIntegratorOutport1, &In1_1s, &Out2_1s);

  /* TaskTransBlk generated from: '<Root>/SS2' */
  rtDW.TmpTaskTransAtSS2Outport1_buf_2[rtDW.fw_buf_2] = Out2_1s;
  rtw_win_mutex_wait(rtDW.mw_buf_2);
  rtDW.fw_buf_2 = 1 - rtDW.fw_buf_2;
  rtw_win_mutex_release(rtDW.mw_buf_2);
}

/* OutputUpdate for Task: PeriodicTrigger1_TwoSecond */
void PeriodicTrigger1_TwoSecond_step(void) /* Sample time: [2.0s, 0.0s] */
{
  {
    int8_T wrBufIdx;

    /* ModelReference: '<Root>/Integrator' incorporates:
     *  Inport: '<Root>/In2_2s'
     */
    integrator(&In2_2s, &rtDW.Integrator, &(rtDW.Integrator_InstanceData.rtdw));

    /* RateTransition generated from: '<Root>/Integrator' */
    rtw_win_mutex_wait(rtDW.TmpRTBAtIntegratorOutport1_d0_SEMAPHORE);
    wrBufIdx = (int8_T)(rtDW.TmpRTBAtIntegratorOutport1_LstBufWR + 1);
    if (wrBufIdx == 3) {
      wrBufIdx = 0;
    }

    if (wrBufIdx == rtDW.TmpRTBAtIntegratorOutport1_RDBuf) {
      wrBufIdx++;
      if (wrBufIdx == 3) {
        wrBufIdx = 0;
      }
    }

    rtw_win_mutex_release(rtDW.TmpRTBAtIntegratorOutport1_d0_SEMAPHORE);
    rtDW.TmpRTBAtIntegratorOutport1_Buf[wrBufIdx] = rtDW.Integrator;
    rtDW.TmpRTBAtIntegratorOutport1_LstBufWR = wrBufIdx;

    /* End of RateTransition generated from: '<Root>/Integrator' */
  }
}

/* OutputUpdate for Task: PeriodicTrigger2_OneSecond */
void PeriodicTrigger2_OneSecond_step(void) /* Sample time: [1.0s, 0.0s] */
{
  {
    real_T rtb_TmpTaskTransAtSumInport1;
    int_T wrBufIdx;

    /* TaskTransBlk generated from: '<Root>/Sum' */
    rtw_win_mutex_wait(rtDW.mw_buf_1);
    wrBufIdx = 1 - rtDW.fw_buf_1;
    rtw_win_mutex_release(rtDW.mw_buf_1);
    rtb_TmpTaskTransAtSumInport1 = rtDW.TmpTaskTransAtSS1Outport1_buf_1[wrBufIdx];

    /* TaskTransBlk generated from: '<Root>/Sum' */
    rtw_win_mutex_wait(rtDW.mw_buf_2);
    wrBufIdx = 1 - rtDW.fw_buf_2;
    rtw_win_mutex_release(rtDW.mw_buf_2);

    /* ModelReference: '<Root>/Sum' incorporates:
     *  TaskTransBlk generated from: '<Root>/Sum'
     */
    sumsys(&rtb_TmpTaskTransAtSumInport1,
           &rtDW.TmpTaskTransAtSS2Outport1_buf_2[wrBufIdx], &Out1_1s);
  }
}

void concurrent_execution_step(int_T tid)
{
  switch (tid) {
   case 0 :
    PeriodicTrigger1_OneSecond_step();
    break;

   case 1 :
    PeriodicTrigger1_TwoSecond_step();
    break;

   case 2 :
    PeriodicTrigger2_OneSecond_step();
    break;

   default :
    break;
  }
}

/* Model initialize function */
void concurrent_execution_initialize(void)
{
  /* Registration code */
  {
    /* user code (registration function declaration) */
    int_T tIdx;
    for (tIdx = 0; tIdx < 3; tIdx++) {
      task_M[tIdx] = &task_M_[tIdx];

      /* initialize real-time model */
      (void) memset((void *) task_M[tIdx], 0,
                    sizeof(RT_MODEL));
    }
  }

  /* Model Initialize function for ModelReference Block: '<Root>/Integrator' */
  integrator_initialize(rtmGetErrorStatusPointer(rtM),
                        &(rtDW.Integrator_InstanceData.rtm));

  /* Model Initialize function for ModelReference Block: '<Root>/SS1' */
  ss1_initialize(rtmGetErrorStatusPointer(rtM), &(rtDW.SS1_InstanceData.rtm));

  /* Model Initialize function for ModelReference Block: '<Root>/SS2' */
  ss2_initialize(rtmGetErrorStatusPointer(rtM), &(rtDW.SS2_InstanceData.rtm));

  /* Model Initialize function for ModelReference Block: '<Root>/Sum' */
  sumsys_initialize(rtmGetErrorStatusPointer(rtM), &(rtDW.Sum_InstanceData.rtm));

  /* Start for RateTransition generated from: '<Root>/Integrator' */
  rtw_win_mutex_create(&rtDW.TmpRTBAtIntegratorOutport1_d0_SEMAPHORE);

  /* InitializeConditions for TaskTransBlk generated from: '<Root>/SS1' */
  rtw_win_mutex_create(&rtDW.mw_buf_1);

  /* InitializeConditions for TaskTransBlk generated from: '<Root>/SS2' */
  rtw_win_mutex_create(&rtDW.mw_buf_2);
}

/* Model terminate function */
void concurrent_execution_terminate(void)
{
  /* Terminate for RateTransition generated from: '<Root>/Integrator' */
  rtw_win_mutex_close(rtDW.TmpRTBAtIntegratorOutport1_d0_SEMAPHORE);

  /* Terminate for TaskTransBlk generated from: '<Root>/SS1' */
  rtw_win_mutex_close(rtDW.mw_buf_1);

  /* Terminate for TaskTransBlk generated from: '<Root>/SS2' */
  rtw_win_mutex_close(rtDW.mw_buf_2);
}

/*
 * File trailer for generated code.
 *
 * [EOF]
 */
